package cn.turboinfo.fuyang.api.scheduler.listener.order

import cn.turboinfo.fuyang.api.domain.common.service.company.HousekeepingCompanyService
import cn.turboinfo.fuyang.api.domain.common.service.custom.ServiceCustomService
import cn.turboinfo.fuyang.api.domain.common.service.order.ServiceOrderService
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService
import cn.turboinfo.fuyang.api.domain.common.service.shop.HousekeepingShopService
import cn.turboinfo.fuyang.api.domain.common.service.staff.HousekeepingStaffService
import cn.turboinfo.fuyang.api.entity.common.constant.EventConstants
import cn.turboinfo.fuyang.api.entity.common.enumeration.custom.ServiceCustomStatus
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderStatus
import cn.turboinfo.fuyang.api.entity.common.event.order.ServiceOrderStatusChangedEvent
import cn.turboinfo.fuyang.api.provider.rabbit.constant.RabbitConstants
import mu.KotlinLogging
import org.springframework.amqp.core.Binding
import org.springframework.amqp.core.BindingBuilder
import org.springframework.amqp.core.Queue
import org.springframework.amqp.core.TopicExchange
import org.springframework.amqp.rabbit.annotation.RabbitHandler
import org.springframework.amqp.rabbit.annotation.RabbitListener
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.stereotype.Component

/**
 * 服务订单数量重算
 */
@Configuration
class ServiceOrderCountRecalculateListenerConfig {

    companion object {
        private const val Name = "ServiceOrderCountRecalculate"

        private const val Topic = EventConstants.TopicServiceOrderStatusChangedEvent

        const val QueueName =
            "${RabbitConstants.QueueEventPrefix}${Topic}.${Name}"

        const val RoutingKey = "${RabbitConstants.RoutingKeyEventPrefix}${Topic}"
    }


    @Bean
    fun serviceOrderCountRecalculateQueue(): Queue {
        return Queue(QueueName)
    }

    @Bean
    protected fun serviceOrderCountRecalculateBinding(
        serviceOrderCountRecalculateQueue: Queue,
        eventExchange: TopicExchange
    ): Binding {
        return BindingBuilder.bind(serviceOrderCountRecalculateQueue)
            .to(eventExchange)
            .with(RoutingKey)
    }

    @Component
    @RabbitListener(queues = [QueueName])
    class ServiceOrderCountRecalculateListener(
        private val serviceOrderService: ServiceOrderService,
        private val serviceCustomService: ServiceCustomService,
        private val productService: ProductService,
        private val housekeepingStaffService: HousekeepingStaffService,
        private val housekeepingShopService: HousekeepingShopService,
        private val housekeepingCompanyService: HousekeepingCompanyService,
    ) {

        private val logger = KotlinLogging.logger {}

        @RabbitHandler
        fun process(event: ServiceOrderStatusChangedEvent) {
            runCatching {
                event
                    .takeIf {
                        // 暂时只统计已完成的
                        it.status == ServiceOrderStatus.COMPLETED
                    }
                    ?.also { event ->
                        // 拿到服务订单详情
                        val serviceOrder = serviceOrderService.getByIdEnsure(event.serviceOrderId)

                        // 服务产品ID
                        val productId = serviceOrder.productId
                        calculateProductCount(productId)

                        // 对订单进行服务的员工ID
                        val staffId = serviceOrder.staffId
                        calculateStaffCount(staffId)

                        // 所属门店ID
                        val shopId = serviceOrder.shopId
                        calculateShopCount(shopId)

                        // 所属公司ID
                        val companyId = serviceOrder.companyId
                        calculateCompanyCount(companyId)
                    }
            }
                .onFailure {
                    logger.error(it) { "处理信用评价重算事件消息出错" }
                }
        }

        private fun calculateProductCount(productId: Long) {
            // 取该产品的所有历史服务过的订单计算
            // TODO 暂时简单粗暴全拿出来使用
            val orderList = serviceOrderService.findByProductId(productId, ServiceOrderStatus.COMPLETED)
            productService.updateOrderNum(productId, orderList.size.toLong())
        }

        private fun calculateStaffCount(staffId: Long) {
            // 取该服务人员的所有历史服务过的订单计算
            // TODO 暂时简单粗暴全拿出来使用
            val customList = serviceCustomService.findByStaffId(staffId, ServiceCustomStatus.COMPLETED)
            val orderList = serviceOrderService.findByStaffId(staffId, ServiceOrderStatus.COMPLETED)
            housekeepingStaffService.updateOrderNum(staffId, orderList.size.toLong() + customList.size.toLong())
        }

        private fun calculateShopCount(shopId: Long) {
            // 取该门店的所有历史服务过的订单计算
            // TODO 暂时简单粗暴全拿出来使用
            val customList = serviceCustomService.findByShopId(shopId, ServiceCustomStatus.COMPLETED)
            val orderList = serviceOrderService.findByShopId(shopId, ServiceOrderStatus.COMPLETED)
            housekeepingShopService.updateOrderNum(shopId, orderList.size.toLong() + customList.size.toLong())
        }

        private fun calculateCompanyCount(companyId: Long) {
            // 取该公司的所有历史服务过的订单计算
            // TODO 暂时简单粗暴全拿出来使用
            val customList = serviceCustomService.findByCompanyId(companyId, ServiceCustomStatus.COMPLETED)
            val orderList = serviceOrderService.findByCompanyId(companyId, ServiceOrderStatus.COMPLETED)
            housekeepingCompanyService.updateOrderNum(companyId, orderList.size.toLong() + customList.size.toLong())
        }
    }
}
